from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, BackgroundTasks, Query
from pydantic import BaseModel
from sqlalchemy.orm import Session
from app.api.deps import get_db, get_current_user, get_current_admin_user
from app.models.user import User
from app.schemas.product import ProductCreate, ProductResponse, ProductListResponse
from app.crud.product import product_crud
from app.crud.ai_workflow import ai_workflow
from app.services.tencent.cos_service import TencentCOSService
from app.services.tencent.image_recognition import TencentImageRecognitionService
from app.services.image.processor import ImageProcessor
from app.core.database import SessionLocal
import aiohttp
import uuid
import time
import json
import asyncio
import re
from datetime import datetime
from PIL import Image
import io
import logging

router = APIRouter()
logger = logging.getLogger(__name__)

# 依赖注入
def get_cos_service() -> TencentCOSService:
    return TencentCOSService()

def get_image_service() -> TencentImageRecognitionService:
    return TencentImageRecognitionService()

def get_image_processor() -> ImageProcessor:
    return ImageProcessor()

async def download_image_from_url(url: str) -> bytes:
    """从URL下载图片数据"""
    # 配置连接器以解决SSL和连接管理问题
    connector = aiohttp.TCPConnector(
        limit=20,
        limit_per_host=10,
        keepalive_timeout=60,
        enable_cleanup_closed=True,
        ssl=False  # 禁用SSL验证以避免SSL握手问题
    )
    async with aiohttp.ClientSession(connector=connector, timeout=aiohttp.ClientTimeout(total=60)) as session:
        async with session.get(url) as response:
            if response.status == 200:
                return await response.read()
            else:
                raise Exception(f"下载图片失败，状态码: {response.status}")

async def upload_image_to_tiia(
    image_url: str,
    group_id: str,
    source_type: str,
    source_index: int,
    cos_service: TencentCOSService,
    image_service: TencentImageRecognitionService,
    processor: ImageProcessor
) -> dict:
    """上传图片到腾讯云并添加到图片库"""
    try:
        # 1. 下载原图片
        image_data = await download_image_from_url(image_url)
        
        # 2. 获取图片尺寸
        image_obj = Image.open(io.BytesIO(image_data))
        width, height = image_obj.size
        
        # 3. 处理为JPEG格式（确保兼容性）
        processed_image_data = processor.to_jpeg(image_data)
        
        # 4. 生成唯一文件名
        pic_name = f"{source_type}_{source_index}_{int(time.time())}_{uuid.uuid4().hex[:8]}.jpg"
        
        # 5. 上传到COS - 修复方法名与参数
        cos_result = cos_service.upload_image(
            image_data=processed_image_data,
            file_extension='jpg',
            folder=group_id
        )
        
        # 6. 添加到腾讯云图片库 - 使用Base64并修复方法名（不再传 Tags）
        image_base64 = processor.bytes_to_base64(processed_image_data)
        tiia_result = image_service.add_image_to_group(
            group_id=group_id,
            entity_id=pic_name,  # 使用pic_name作为entity_id，保证唯一
            image_base64=image_base64,
            pic_name=pic_name
        )
        
        return {
            "cos_url": cos_result["url"],
            "cos_key": cos_result["key"],
            "width": width,
            "height": height,
            "pic_name": pic_name,
        }
        
    except Exception as e:
        logger.error(f"上传图片到TIIA失败: {str(e)}")
        raise

def extract_image_url_from_markdown(content):
    """从markdown格式的内容中提取图片URL"""
    if not content:
        return None
    
    # 匹配各种格式的图片URL
    url_patterns = [
        r'!\s*`([^`]+)`',  # ! `url` 格式
        r'!\[.*?\]\(([^)]+)\)',  # ![alt](url) 格式
        r'`(https?://[^`]+)`',   # `url` 格式
        r'(https?://[^\s\)]+)'   # 直接的URL
    ]
    
    for pattern in url_patterns:
        match = re.search(pattern, content)
        if match:
            return match.group(1).strip()
    
    return None

@router.post("/import-workflow-products/{workflow_id}")
async def import_workflow_products(
    workflow_id: int,
    background_tasks: BackgroundTasks,
    group_id: str = "8",
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
    cos_service: TencentCOSService = Depends(get_cos_service),
    image_service: TencentImageRecognitionService = Depends(get_image_service),
    processor: ImageProcessor = Depends(get_image_processor)
):
    """导入工作流的产品数据到产品表并上传到腾讯云图片库"""
    
    # 1. 验证工作流是否存在且属于当前用户
    workflow = ai_workflow.get_workflow(db=db, workflow_id=workflow_id)
    if not workflow:
        raise HTTPException(status_code=404, detail="工作流不存在")
    
    if workflow.user_id != current_user.id:
        raise HTTPException(status_code=403, detail="没有权限访问此工作流")
    
    # 强制固定使用 group_id = "8"
    group_id = "8"
    
    # 2. 获取工作流结果数据
    result_data = workflow.result_data or {}
    detail_pages = result_data.get('detail_pages', [])
    
    # 新逻辑：仅以 detail_pages 为准创建产品
    if not detail_pages:
        raise HTTPException(status_code=400, detail="工作流中没有可导入的详情页数据")
    
    # 3. 读取已存在的产品，基于 workflow_id+index 做增量导入
    pending_detail = [
        (idx, item) for idx, item in enumerate(detail_pages)
        if not product_crud.exists_by_workflow_and_index(db=db, workflow_id=workflow_id, source_index=idx)
    ]
    
    if not pending_detail:
        raise HTTPException(status_code=400, detail="该工作流的可导入产品均已导入，无需重复导入")
    
    # 4. 启动后台任务，仅传递 detail_pages 的待导入项
    background_tasks.add_task(
        process_product_import,
        workflow_id,
        pending_detail,  # [(original_index, detail_item), ...]
        group_id,
        current_user.id
    )
    
    return {
        "code": 200,
        "msg": "产品导入任务已启动（按详情页增量导入未导入项）",
        "data": {
            "workflow_id": workflow_id,
            "pending_detail_pages_count": len(pending_detail),
            "estimated_total": len(pending_detail)
        }
    }

async def process_product_import(
    workflow_id: int,
    detail_pages: List[tuple],     # [(original_index, detail_item), ...]
    group_id: str,
    user_id: int
):
    """后台处理产品导入任务（按详情页创建产品）"""
    try:
        # 创建新的数据库会话用于后台任务
        db = SessionLocal()
        cos_service = TencentCOSService()
        image_service = TencentImageRecognitionService()
        processor = ImageProcessor()
        
        success_count = 0
        error_count = 0
        
        # 仅处理 detail_pages - 使用原始索引
        for original_index, detail_item in detail_pages:
            try:
                image_url = detail_item.get('image_url')
                if not image_url:
                    logger.warning(f"detail_page {original_index} 没有图片URL，跳过")
                    continue

                # 幂等：若该索引已存在产品，则跳过（与来源类型无关）
                if product_crud.exists_by_workflow_and_index(db=db, workflow_id=workflow_id, source_index=original_index):
                    logger.info(f"⏭️ index {original_index} 的产品已存在，跳过")
                    continue

                # 仅构造产品自身的 product_tags（用于存库），不再给腾讯侧准备 tags
                raw_tags = detail_item.get('product_tags')
                product_tags = None
                if isinstance(raw_tags, str) and raw_tags.strip():
                    tags_list = [tag.strip() for tag in raw_tags.split(',') if tag.strip()]
                    try:
                        product_tags = json.dumps(tags_list, ensure_ascii=False)
                    except Exception:
                        product_tags = None
                elif isinstance(raw_tags, list):
                    cleaned = [str(t).strip() for t in raw_tags if str(t).strip()]
                    try:
                        product_tags = json.dumps(cleaned, ensure_ascii=False)
                    except Exception:
                        product_tags = None
                elif isinstance(raw_tags, dict):
                    try:
                        product_tags = json.dumps(raw_tags, ensure_ascii=False)
                    except Exception:
                        product_tags = None

                upload_result = await upload_image_to_tiia(
                    image_url=image_url,
                    group_id=group_id,
                    source_type="detail_page",
                    source_index=original_index,
                    cos_service=cos_service,
                    image_service=image_service,
                    processor=processor
                )

                # 从 detail_content 中提取图片URL（支持markdown格式）
                detail_content = detail_item.get('detail_content')
                detail_image_url = extract_image_url_from_markdown(detail_content) or image_url

                # 创建产品记录
                product_data = ProductCreate(
                    workflow_id=workflow_id,
                    user_id=user_id,
                    product_title=detail_item.get('product_title') or f"详情页图片 #{original_index + 1}",
                    product_tags=product_tags,
                    product_description=detail_item.get('product_description'),
                    image_url=image_url,
                    image_width=upload_result['width'],
                    image_height=upload_result['height'],
                    entity_id=upload_result['pic_name'],
                    cos_url=upload_result['cos_url'],
                    cos_key=upload_result['cos_key'],
                    source_type="detail_page",
                    source_index=original_index,
                    detail_content=detail_image_url
                )
                product_crud.create_product(db=db, obj_in=product_data)
                success_count += 1
                logger.info(f"✅ detail_page {original_index} 导入成功")
            except Exception as e:
                error_count += 1
                logger.error(f"❌ detail_page {original_index} 导入失败: {str(e)}")
                continue
        
        logger.info(f"🎉 产品导入任务完成: 成功 {success_count} 个，失败 {error_count} 个")
        
    except Exception as e:
        logger.error(f"❌ 产品导入任务异常: {str(e)}")
    finally:
        # 确保关闭数据库会话
        db.close()

@router.get("/workflow/{workflow_id}", response_model=ProductListResponse)
def get_workflow_products(
    workflow_id: int,
    skip: int = 0,
    limit: int = -1,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """获取工作流的产品列表"""
    
    # 验证工作流权限
    workflow = ai_workflow.get_workflow(db=db, workflow_id=workflow_id)
    if not workflow:
        raise HTTPException(status_code=404, detail="工作流不存在")
    
    if workflow.user_id != current_user.id:
        raise HTTPException(status_code=403, detail="没有权限访问此工作流")
    
    # 获取产品列表（limit < 0 时返回全部）
    if limit is not None and limit >= 0:
        products = product_crud.get_products_by_workflow(
            db=db, 
            workflow_id=workflow_id,
            skip=skip,
            limit=limit
        )
    else:
        products = product_crud.get_all_products_by_workflow(db=db, workflow_id=workflow_id)
    
    total = product_crud.get_products_count_by_workflow(db=db, workflow_id=workflow_id)
    
    return ProductListResponse(
        data=products,
        total=total
    )


@router.get("/{product_id}", response_model=ProductResponse, summary="获取产品详情", description="所有已登录用户均可查看")
def get_product_detail(
    product_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """获取单个产品详情（已登录用户可查看任意产品）"""
    product = product_crud.get_product(db=db, product_id=product_id)
    if not product:
        raise HTTPException(status_code=404, detail="产品不存在")
    # 取消“只能本人查看”的权限限制
    return product

# 添加请求模型
class BatchDeleteRequest(BaseModel):
    product_ids: List[int]
    
class BatchDeleteResponse(BaseModel):
    success_count: int
    failed_count: int
    failed_ids: List[int]
    message: str

@router.delete("/batch/delete", response_model=BatchDeleteResponse)
def delete_products_batch(
    request: BatchDeleteRequest,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_admin_user)
):
    """批量删除产品（仅管理员）"""
    
    if not request.product_ids:
        raise HTTPException(status_code=400, detail="产品ID列表不能为空")
    
    # 移除数量限制
    # if len(request.product_ids) > 100:  # 限制批量删除数量
    #     raise HTTPException(status_code=400, detail="单次最多删除100个产品")
    
    # 执行批量删除（管理员可以删除任何产品）
    result = product_crud.delete_products_batch_admin(
        db=db, 
        product_ids=request.product_ids
    )
    
    # 构造响应消息
    if result["failed_count"] == 0:
        message = f"管理员成功删除 {result['success_count']} 个产品"
    else:
        message = f"管理员成功删除 {result['success_count']} 个产品，{result['failed_count']} 个产品删除失败（不存在）"
    
    return BatchDeleteResponse(
        success_count=result["success_count"],
        failed_count=result["failed_count"],
        failed_ids=result["failed_ids"],
        message=message
    )

class WorkflowDeleteResponse(BaseModel):
    success: bool
    deleted_count: int
    message: str

@router.delete("/workflow/{workflow_id}/products", response_model=WorkflowDeleteResponse)
def delete_workflow_products(
    workflow_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_admin_user),
):
    """根据工作流ID删除所有相关产品（仅管理员）"""
    
    # 验证工作流是否存在
    workflow = ai_workflow.get_workflow(db=db, workflow_id=workflow_id)
    if not workflow:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="工作流不存在"
        )
    
    # 执行删除操作
    result = product_crud.delete_products_by_workflow(db=db, workflow_id=workflow_id)
    
    if not result["success"]:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=result["message"]
        )
    
    return WorkflowDeleteResponse(
        success=result["success"],
        deleted_count=result["deleted_count"],
        message=result["message"]
    )


# 首先添加新的响应模型
class TagSearchProductItem(BaseModel):
    id: int
    entity_id: Optional[str]
    pic_name: str  # 对应 product_title
    cos_url: Optional[str]
    width: Optional[int]  # 对应 image_width
    height: Optional[int]  # 对应 image_height
    file_size: Optional[int] = None
    created_at: datetime

class RelatedTag(BaseModel):
    """相关标签模型"""
    tag: str
    count: int
    weight: float

class TagSearchResponse(BaseModel):
    success: bool
    data: List[TagSearchProductItem]  # 改为 data
    total: int
    page: int
    page_size: int
    tags: List[str]
    match_mode: str
    related_tags: List[RelatedTag]  # 新增：相关标签列表

@router.get("/search/tags", response_model=TagSearchResponse)
def search_products_by_tags(
    tags: str = Query(..., description="搜索标签，多个标签用逗号分隔"),
    match_mode: str = Query("any", regex="^(any|all)$", description="匹配模式：any(任一标签) 或 all(所有标签)"),
    page: int = Query(1, ge=1, description="页码"),
    page_size: int = Query(20, ge=1, le=100, description="每页数量"),
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """根据标签搜索产品"""
    
    # 解析标签
    tag_list = [tag.strip() for tag in tags.split(',') if tag.strip()]
    
    if not tag_list:
        raise HTTPException(
            status_code=400,
            detail="请提供至少一个搜索标签"
        )
    
    # 计算分页参数
    skip = (page - 1) * page_size
    
    # 执行搜索
    products, total = product_crud.search_products_by_tags(
        db=db,
        tags=tag_list,
        match_mode=match_mode,
        skip=skip,
        limit=page_size
    )
    
    # 获取所有匹配的产品（不分页）用于统计相关标签
    all_products, _ = product_crud.search_products_by_tags(
        db=db,
        tags=tag_list,
        match_mode=match_mode,
        skip=0,
        limit=1000  # 限制最多1000个产品用于标签统计
    )
    
    # 统计相关标签
    tag_counter = {}
    for product in all_products:
        if product.product_tags:
            try:
                # 解析产品标签（支持JSON格式）
                if product.product_tags.startswith('[') or product.product_tags.startswith('{'):
                    product_tag_list = json.loads(product.product_tags)
                    if isinstance(product_tag_list, list):
                        tags_to_count = product_tag_list
                    elif isinstance(product_tag_list, dict):
                        tags_to_count = list(product_tag_list.values())
                    else:
                        tags_to_count = [str(product_tag_list)]
                else:
                    # 普通逗号分隔的标签
                    tags_to_count = [tag.strip() for tag in product.product_tags.split(',') if tag.strip()]
                
                # 统计标签出现次数
                for tag in tags_to_count:
                    tag = str(tag).strip()
                    if tag and tag not in tag_list:  # 排除搜索关键词本身
                        tag_counter[tag] = tag_counter.get(tag, 0) + 1
            except (json.JSONDecodeError, Exception):
                # 如果解析失败，尝试按逗号分割
                tags_to_count = [tag.strip() for tag in product.product_tags.split(',') if tag.strip()]
                for tag in tags_to_count:
                    if tag and tag not in tag_list:
                        tag_counter[tag] = tag_counter.get(tag, 0) + 1
    
    # 计算权重并排序（按出现次数降序）
    total_tags = sum(tag_counter.values())
    related_tags = []
    if total_tags > 0:
        sorted_tags = sorted(tag_counter.items(), key=lambda x: x[1], reverse=True)
        related_tags = [
            RelatedTag(
                tag=tag,
                count=count,
                weight=round(count / total_tags, 4)
            )
            for tag, count in sorted_tags[:20]  # 最多返回20个相关标签
        ]
    
    # 转换数据格式
    data = [
        TagSearchProductItem(
            id=product.id,
            entity_id=product.entity_id,
            pic_name=product.product_title,
            cos_url=product.cos_url,
            width=product.image_width,
            height=product.image_height,
            file_size=None,  # 如果需要文件大小，需要在Product模型中添加此字段
            created_at=product.created_at
        )
        for product in products
    ]
    
    return TagSearchResponse(
        success=True,
        data=data,  # 使用 data 而不是 products
        total=total,
        page=page,
        page_size=page_size,
        tags=tag_list,
        match_mode=match_mode,
        related_tags=related_tags
    )